#ifndef __MESSAGE_QUEUE_H
#define __MESSAGE_QUEUE_H

#include "../rtx/rtx_os.h"
#include "../utils/nocopyable.h"

namespace rtos {

template <typename MsgType, uint32_t Capacity>
class MessageQueue : utils::NoCopyable {
public:
    static constexpr uint32_t MsgSize = sizeof(MsgType);
    static constexpr uint32_t MqSize =
        osRtxMessageQueueMemSize(Capacity, MsgSize);

    void init(const char *name = "other") {
        osMessageQueueAttr_t attr;
        attr.name = name;
        attr.attr_bits = 0;
        attr.cb_mem = m_cb_mem;
        attr.cb_size = osRtxMessageQueueCbSize;
        attr.mq_mem = m_mq_mem;
        attr.mq_size = MqSize;
        m_id = osMessageQueueNew(Capacity, MsgSize, &attr);
    }

    inline osStatus_t post(const MsgType &msg) {
        return osMessageQueuePut(m_id, &msg, 0, 0);
    }

    inline osStatus_t poll(MsgType &msg, uint32_t timeout = osWaitForever) {
        return osMessageQueueGet(m_id, &msg, NULL, timeout);
    }

    inline osStatus_t get(MsgType &msg) {
        return osMessageQueueGet(m_id, &msg, NULL, 0);
    }

    inline MsgType take() {
        MsgType m;
        osMessageQueueGet(m_id, &m, NULL, osWaitForever);
        return m;
    }

    inline osStatus_t reset() { return osMessageQueueReset(m_id); }

private:
    osMessageQueueId_t m_id;
    uint64_t m_cb_mem[(osRtxMessageQueueCbSize + 7) / 8];
    uint64_t m_mq_mem[(MqSize + 7) / 8];
};

} // namespace rtos

#endif
